#ifndef CANFILTER_H
#define CANFILTER_H

#include "QWidget"
#include "FrameBase.h"


struct CAN_FrameFiltered{
   bool success;
   FrameType type;
   FrameSize size;
   uint32_t ID;
   FrameData data;
   uint8_t dataLen;
};


/* @CANFilter
 * 作为CAN协议的过滤器，允许指定的ID通过
 * 允许通过的ID：和MASK掩膜相与符合的ID.
 */
class CANFilter:public CAN_FrameBase{
public:
    CANFilter(){}
    CANFilter(uint32_t ID):passedID(ID){};
    CANFilter(uint32_t ID,uint8_t Bytes):passedID(ID),bytesLen(Bytes){}
    CANFilter(uint32_t ID,uint8_t bytes,bool en_crc):passedID(ID),bytesLen(bytes),EN_CRC_Check(en_crc){}

    void config(uint32_t ID,uint32_t mask,uint8_t bytes,bool en_crc){
        passedID = ID;MASK = mask; bytesLen = (bytes);EN_CRC_Check = en_crc;
    }
    void enCRC(bool val){EN_CRC_Check = val;}
    void setDataLen(uint8_t len){bytesLen = len;}
    void setPassedID(uint32_t id){passedID = id;}
    void setMASK(uint32_t mask){MASK = mask;}

    CAN_FrameFiltered getFilteredData(const uint8_t* frame);


private:
    uint32_t passedID = 0;
    uint32_t MASK = 0;
    uint8_t bytesLen = 1;
    bool EN_CRC_Check = true;
};

CAN_FrameFiltered CANFilter::getFilteredData(const canU8_t* frame){
    CAN_FrameFiltered out;
    canU8_t crcData[20];

    if(getBit(frame,1,eIDE_MOVE))
    { // 如果是扩展帧
        out.size = Expanded;
        uint16_t std = getBit(frame,11,eStdId_MOVE);
        uint32_t ext = getBit(frame,18,eExtId_MOVE);
        out.ID = std | (ext << 11);

        if(getBit(frame,1,eRTR_MOVE))
        {  // 如果是远程帧
            out.type = TypeRequest;
            out.dataLen = getBit(frame,4,eDLC_MOVE);
        }
        else
        {   // 如果是数据帧
            out.type = TypeData;
            out.dataLen = getBit(frame,4,eDLC_MOVE);
            for(int i = 0;i < out.dataLen;i++) // 数据赋值
            {
                out.data.dataU8[i] = getBit(frame,8,eData0_MOVE + i*8);
            }
        }
    }
    else
    {   // 如果是标准帧
        out.size = Standard;
        out.ID = getBit(frame,11,sStdId_MOVE);
        if(getBit(frame,1,sRTR_MOVE))
        {   // 如果是远程帧
            out.type = TypeRequest;
            out.dataLen = getBit(frame,4,sDLC_MOVE);
        }
        else
        {   // 如果是数据帧
            out.type = TypeData;
            out.dataLen = getBit(frame,4,sDLC_MOVE);
            for(int i = 0;i < out.dataLen;i++)
            {
                out.data.dataU8[i] = getBit(frame,8,sData0_MOVE + i*8);
            }
        }
    }

    if(out.ID == (MASK & passedID))
    {// TODO:编写ID校验通过的代码
        out.success = true;
    }
    if(EN_CRC_Check)
    { // 如果使能了CRC校验
        int bits;
        if(out.size == Standard)
        {// 如果是标准帧
            bits = stCRCBitsBase + out.dataLen * 8;
        }
        else
        {// 如果是扩展帧
            bits = exCRCBitsBase + out.dataLen * 8;
        }
        int bytes = (float)(bits/8.0f) > (int)(bits/8)? (int)(bits/8 + 1) : (int)(bits/8);
        for(int i = 0;i < bytes;i++)// 取出需要校验的字节
        {
            crcData[i] = frame[i];
        }
        crcData[bytes - 1] &= 0X07;    // 标准帧的最高字节
        uint16_t crc = getBit(frame,15,sCRC_MOVE + 8 * out.dataLen);
        // TODO:编写CRC校验的程序

    }
    return out;
}

#endif // CANFILTER_H


